function study(language: { name: string, age: () => number }) {
    console.log(`ProgramLanguage ${language.name} created ${language.age()} years ago.`);
}
// test 1
study({
    name: 'TypeScript',
    age: () => 10,
    // id: 1 对象文字可以只指定已知属性，并且“id”不在类型“
});
// ProgramLanguage TypeScript created 10 years ago.

// test 2
const stu = {
    id: 1,
    name: 'Javascript',
    age: () => new Date().getFullYear() - 2000
}
study(stu)
// ProgramLanguage Javascript created 22 years ago.

interface ProgramLanguage {
    readonly name: string,
    age: () => number,
    desc?: string,//可缺省变量
}
const lan: ProgramLanguage = {
    name: 'Javasript',
    age: () => new Date().getFullYear() - 1970
}
// lan.name = 'abc' 无法分配到 "name" ，因为它是只读属性
lan.desc = '超厉害'

// 索引签名
{
    interface StringMap {
        [prop: string]: number
        age: number
        // name: string
        // 类型“string”的属性“name”不能赋给“string”索引类型“number”。ts(2411)
    }
}

// 继承与实现
{
    interface A extends ProgramLanguage {
        rank: number
    }
    interface B extends ProgramLanguage {
        checker: boolean
    }
    interface C extends A, B {
        top_public: boolean
    }
}

// Type 类型别名
{
    type LanguageType = {
        name: string,
        age: () => number
    }
}

// 重复定义接口类型
{
    interface Language {
        id: number
    }
    interface Language {
        name: string
    }
    const lan: Language = {
        id: 1,
        name: 'name'
    }
}
{
    // 标识符“Language”重复
    type Language {
        id: number
    }
    // 标识符“Language”重复
    // type Language {
    //     name: string
    // }
    const lan: Language = {
        id: 1,
        // name: 'name'
    }
}